package game.ouroboros.screens;

import java.util.List;
import javax.microedition.khronos.opengles.GL10;
import android.util.Log;
import framework.Engine;
import framework.Input.TouchEvent;
import framework.graphics.opengl.Camera2D;
import framework.graphics.opengl.GLScreen;
import framework.graphics.opengl.SpriteBatcher;
import framework.maths.CollisionTester;
import framework.maths.Rectangle;
import framework.maths.Vector2;
import game.ouroboros.Assets;
import game.ouroboros.magic.JigokuManager;
import game.ouroboros.magic.Menu;
import game.ouroboros.magic.World;
import game.ouroboros.magic.WorldRenderer;
import game.ouroboros.traps.ElectricArc;
import game.ouroboros.traps.EnergyField;
import game.ouroboros.traps.Estalactites;
import game.ouroboros.traps.FlameThrower;
import game.ouroboros.traps.Geiser;
import game.ouroboros.traps.GiantBoulder;
import game.ouroboros.traps.LavaDig;
import game.ouroboros.traps.SpikeBarrier;
import game.ouroboros.traps.Tornado;
import game.ouroboros.traps.Trap;
import game.ouroboros.traps.WaterShooter;
import game.ouroboros.traps.WaterSlide;
import game.ouroboros.traps.WindBreaker;

public class RunningGameScreen extends GLScreen {
	static final int GAME_PREPARING = 0;
	static final int GAME_RUNNING = 1;
	static final int GAME_PAUSED = 2;
	static final int GAME_LEVEL_END = 3;
	static final int GAME_OVER = 4;
	static final int GAME_OVERLOOKING = 666;
	int state;

	Camera2D guiCam;
	Vector2 touchPoint;
	SpriteBatcher batcher;
	World world;
	WorldRenderer renderer;
	Rectangle pauseBounds;
	Rectangle resumeBounds;
	Rectangle quitBounds;
	int lastScore;
	String scoreString;
	Menu menu;

	public JigokuManager manaManager;

	public int level;

	public RunningGameScreen(Engine engine) {
		super(engine);
		this.level = 0;
		this.manaManager = new JigokuManager(2000);

		Log.v("<Chamada>", "RunningGameScreen()");
		state = GAME_PREPARING;
		guiCam = new Camera2D(glGraphics, 320, 480);
		touchPoint = new Vector2();
		batcher = new SpriteBatcher(glGraphics, 1000);
		Log.v("<FIM>", "RunningGameScreen(): batcher criado");
		world = new World(100 , 100, 32, 32);
		Log.v("<FIM>", "RunningGameScreen(): world criado");
		renderer = new WorldRenderer(glGraphics, batcher, world);
		Log.v("<FIM>", "RunningGameScreen(): Renderer criado");
		pauseBounds = new Rectangle(320 - 64, 480 - 64, 64, 64);
		resumeBounds = new Rectangle(160 - 96, 240, 192, 36);
		quitBounds = new Rectangle(160 - 96, 240 - 36, 192, 36);
		lastScore = 0;
		scoreString = "score: 0";

		Log.v("<FIM>", "RunningGameScreen()");
		this.menu = new Menu(world.getTrapManager(), glGame);
	}

	@Override
	public void update(float deltaTime) {

		Log.v("<Chamada>", "RunningGameScreen().update()");
		Log.v("<STATE>", "      STATE: " + state);

		if (deltaTime > 0.1f)
			deltaTime = 0.1f;

		switch (state) {
		case GAME_PREPARING:
			updatePreparing(deltaTime);
			/**
			 * TODO
			 */
			break;
		case GAME_OVERLOOKING:
			world.generateLevel();
			state = GAME_RUNNING;
			break;
		case GAME_RUNNING:
			updateRunning(deltaTime);
			break;
		case GAME_PAUSED:
			updatePaused();
			break;
		case GAME_LEVEL_END:
			updateLevelEnd();
			break;
		case GAME_OVER:
			updateGameOver();
			engine.setScreen(new MenuGameScreen(engine));
			break;
		}

		Log.v("<FIM>", "RunningGameScreen().update");
	}

	/**
	 * TODO -> verificar quando o usuário terminou de inserir as armadilhas. ->
	 * Mudar para o estado GAME_OVERLOOKING
	 */
	private int chose;

	private Rectangle rectMenu = new Rectangle(0, 400, 320, 80);

	private void updatePreparing(float deltatime) {

		Log.v("<Chamada>", "RunningGameScreen().updateReady()");

		List<TouchEvent> touchEvents = engine.getInput().getTouchEvents();
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			touchPoint.x = event.x;
			touchPoint.y = event.y;
			switch (event.type) {
			case TouchEvent.TOUCH_UP:
				Log.v("<MENU>", "Chose UP : " + event.x+" "+event.y);
				if (isTouchEventInMenu(event)) {
					int touchePosition = menu.touchMenu(event);
					chose = touchePosition;
					Log.v("<MENU>", "Chose: " + chose);
					if (touchePosition == -1)
						continue;
					if (chose == 666) {
						state = GAME_OVERLOOKING;
					}

				} else { // upgrade
					guiCam.touchToWorld(touchPoint);
					if (manaManager.canBathery(JigokuManager.UPGRADE_MANA)) {
						manaManager.batheryMana(JigokuManager.UPGRADE_MANA);
						world.getTrapManager()
								.getTrapAt((int) touchPoint.x,
										(int) touchPoint.y).upgrade();
					}
				}
				break;
			case TouchEvent.TOUCH_DOWN:
				Log.v("<MENU>", "CHOSE: "+chose);
				if (chose == -1)
					continue;
				touchPoint.x =event.x;
				touchPoint.y =event.y;
				guiCam.touchToWorld(touchPoint);
				if (world.getTrapManager().isFree(touchPoint.x, touchPoint.y)) {
					Trap p = null;// TODO verificar mana
					if (!manaManager.canBathery(JigokuManager.CREATE_MANA))
						break;
					Log.v("<MENU>", "Trap Criada");
					switch (chose - 1) {
					case 1:
						p = new ElectricArc(event.x, event.y);
						break;
					case 2:
						p = new EnergyField(event.x, event.y);
						break;
					case 3:
						p = new Estalactites(event.x, event.y);
						break;
					case 4:
						p = new FlameThrower(event.x, event.y);
						break;
					case 5:
						p = new Geiser(event.x, event.y);
						break;
					case 6:
						p = new GiantBoulder(event.x, event.y);
						break;
					case 7:
						p = new LavaDig(event.x, event.y);
						break;
					case 8:
						p = new SpikeBarrier(event.x, event.y);
						break;
					case 9:
						p = new Tornado(event.x, event.y);
						break;
					case 10:
						p = new WaterShooter(event.x, event.y);
						break;
					case 11:
						p = new WaterSlide(event.x, event.y);
						break;
					case 12:
						p = new WindBreaker(event.x, event.y);
						break;
					default:
						break;
					}
					world.getTrapManager().putTrapInXY(p, event.x, event.y);
					world.traps.add(p);
					manaManager.batheryMana(JigokuManager.CREATE_MANA);
				} else
					chose = -1;

				break;
			case TouchEvent.TOUCH_DRAGGED:// mexer o cenário
				moveCenario(event);
				break;
			default:
				Log.v("<NOOOOOOOOOOOOOOOOOOOOOO >", "The gods have abandom me");
				break;
			}
		}

	}

	private void moveCenario(TouchEvent event) {
		// TODO Auto-generated method stub

	}

	private Rectangle menuPosition = new Rectangle(0, 0, 320, 80);
	private boolean isTouchEventInMenu(TouchEvent event) {
		return CollisionTester.pointInRectangle(menuPosition, event.x, event.y);
	}

	private void updateRunning(float deltaTime) {
		Log.v("<Chamada>", "RunningGameScreen().updateRunning()");

		List<TouchEvent> touchEvents = engine.getInput().getTouchEvents();
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type != TouchEvent.TOUCH_UP)
				continue;

			touchPoint.set(event.x, event.y);
			guiCam.touchToWorld(touchPoint);

		}

		world.update(deltaTime);
		 
		if(world.level.levelIsFinished()){
			state = GAME_LEVEL_END;
		}
		if (world.state == World.WORLD_STATE_GAME_OVER) {
			state = GAME_OVER;
		}

		Log.v("<FIM>", "RunningGameScreen().updateRunning()");
	}

	private void updatePaused() {
		Log.v("<Chamada>", "RunningGameScreen()");
		List<TouchEvent> touchEvents = engine.getInput().getTouchEvents();
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type != TouchEvent.TOUCH_UP)
				continue;

			touchPoint.set(event.x, event.y);
			guiCam.touchToWorld(touchPoint);

			if (CollisionTester.pointInRectangle(resumeBounds, touchPoint)) {
				state = GAME_RUNNING;
				return;
			}

			if (CollisionTester.pointInRectangle(quitBounds, touchPoint)) {
				engine.setScreen(new MenuGameScreen(engine));
				return;

			}
		}
	}

	private void updateLevelEnd() {
		List<TouchEvent> touchEvents = engine.getInput().getTouchEvents();
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type != TouchEvent.TOUCH_UP)
				continue;
			renderer = new WorldRenderer(glGraphics, batcher, world);
			manaManager.addMana(66666);
			state = GAME_PREPARING;
		}
	}

	private void updateGameOver() {
		List<TouchEvent> touchEvents = engine.getInput().getTouchEvents();
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type != TouchEvent.TOUCH_UP)
				continue;
			engine.setScreen(new MenuGameScreen(engine));
		}
	}

	@Override
	public void render(float deltaTime) {
		GL10 gl = glGraphics.getGL();
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		
		guiCam.setViewportAndMatrices();
		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		switch (state) {
		case GAME_PREPARING:
			renderer.renderBackground();
			renderer.renderTrapsOnlyNow();
			renderPreparing();
			break;
		case GAME_RUNNING:
			renderer.render();
			break;
		case GAME_PAUSED:
			break;
		case GAME_LEVEL_END:
			break;
		case GAME_OVER:
			break;
		}
		gl.glDisable(GL10.GL_BLEND);
	}

	private void renderPreparing() {
		batcher.beginBatch(Assets.gameGrid);
		batcher.drawExactSprite(0, 400, 240, 80, Assets.gameGridRegion);
		batcher.endBatch();
	}


	@Override
	public void pause() {
		if (state == GAME_RUNNING)
			state = GAME_PAUSED;
	}

	@Override
	public void resume() {
	}

	@Override
	public void dispose() {
	}

}